/*
 * The MIT License (MIT)
 *
 * Original work Copyright (c) 2018 Hex_27
 * v2.0 Copyright (c) 2019 Crypto Morin
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

package me.skymc.taboomenu.version;

import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;

import java.util.*;
import java.util.regex.Pattern;

/*
 * References
 *
 * * * GitHub: https://github.com/CryptoMorin/XMaterial/blob/master/XMaterial.java
 * * Thread: https://www.spigotmc.org/threads/378136/
 * https://minecraft.gamepedia.com/Java_Edition_data_values/Pre-flattening
 * https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html
 * http://docs.codelanx.com/Bukkit/1.8/org/bukkit/Material.html
 * https://www.spigotmc.org/threads/1-8-to-1-13-itemstack-material-version-support.329630/
 * https://minecraft-ids.grahamedgecombe.com/
 * v1: https://pastebin.com/Fe65HZnN
 * v2: 6/15/2019
 */

/**
 * MaterialControl v2.2 - Data Values/Pre-flattening
 * Supports 1.8-1.14
 * 1.13 and above as priority.
 */
public enum MaterialControl {
    ACACIA_BOAT(0, "BOAT_ACACIA"),
    ACACIA_BUTTON(0, "WOOD_BUTTON"),
    ACACIA_DOOR(0, "ACACIA_DOOR_ITEM"),
    ACACIA_FENCE(0, ""),
    ACACIA_FENCE_GATE(0, ""),
    ACACIA_LEAVES(0, "LEAVES_2"),
    ACACIA_LOG(0, "LOG_2"),
    ACACIA_PLANKS(4, "WOOD"),
    ACACIA_PRESSURE_PLATE(0, "WOOD_PLATE"),
    ACACIA_SAPLING(4, "SAPLING"),
    ACACIA_SIGN(0, "SIGN"),
    ACACIA_SLAB(4, "WOOD_STEP", "WOODEN_SLAB", "WOOD_DOUBLE_STEP"),
    ACACIA_STAIRS(0, ""),
    ACACIA_TRAPDOOR(0, "TRAP_DOOR"),
    ACACIA_WALL_SIGN(0, "SIGN_POST", "WALL_SIGN"),
    ACACIA_WOOD(0, "LOG_2"),
    ACTIVATOR_RAIL(0, ""),
    AIR(0, ""),
    ALLIUM(2, "RED_ROSE"),
    ANDESITE(5, "STONEZ"),
    ANDESITE_SLAB(0, ""),
    ANDESITE_STAIRS(0, ""),
    ANDESITE_WALL(0, ""),
    ANVIL(0, ""),
    APPLE(0, ""),
    ARMOR_STAND(0, ""),
    ARROW(0, ""),
    ATTACHED_MELON_STEM(7, "MELON_STEM"),
    ATTACHED_PUMPKIN_STEM(7, "PUMPKIN_STEM"),
    AZURE_BLUET(3, "RED_ROSE"),
    BAKED_POTATO(0, ""),
    BAMBOO(0, "1.14", "SUGAR_CANE"),
    BAMBOO_SAPLING(0, "1.14"),
    BARREL(0, "1.14", "CHEST"),
    BARRIER(0, ""),
    BAT_SPAWN_EGG(65, "MONSTER_EGG"),
    BEACON(0, ""),
    BEDROCK(0, ""),
    BEEF(0, "RAW_BEEF"),
    BEETROOT(0, "BEETROOT_BLOCK"),
    BEETROOTS(0, "BEETROOT"),
    BEETROOT_SEEDS(0, ""),
    BEETROOT_SOUP(0, ""),
    BELL(0, "1.14"),
    BIRCH_BOAT(0, "BOAT_BIRCH"),
    BIRCH_BUTTON(0, "WOOD_BUTTON"),
    BIRCH_DOOR(0, "BIRCH_DOOR_ITEM"),
    BIRCH_FENCE(0, ""),
    BIRCH_FENCE_GATE(0, ""),
    BIRCH_LEAVES(2, "LEAVES"),
    BIRCH_LOG(2, "LOG"),
    BIRCH_PLANKS(2, "WOOD"),
    BIRCH_PRESSURE_PLATE(0, "WOOD_PLATE"),
    BIRCH_SAPLING(2, "SAPLING"),
    BIRCH_SIGN(0, "SIGN"),
    BIRCH_SLAB(2, "WOOD_STEP", "WOODEN_SLAB", "WOOD_DOUBLE_STEP"),
    BIRCH_STAIRS(0, "BIRCH_WOOD_STAIRS"),
    BIRCH_TRAPDOOR(0, "TRAP_DOOR"),
    BIRCH_WALL_SIGN(0, "SIGN_POST", "WALL_SIGN"),
    BIRCH_WOOD(2, "LOG"),
    BLACK_BANNER(0, "BANNER", "STANDING_BANNER"),
    BLACK_BED(15, "BED", "BED_BLOCK"),
    BLACK_CARPET(15, "CARPET"),
    BLACK_CONCRETE(15, "CONCRETE"),
    BLACK_CONCRETE_POWDER(15, "CONCRETE_POWDER"),
    BLACK_DYE(0, "1.14", "INK_SACK"),
    BLACK_GLAZED_TERRACOTTA(15, "1.12", "HARD_CLAY", "STAINED_CLAY", "BLACK_TERRACOTTA"),
    BLACK_SHULKER_BOX(0, ""),
    BLACK_STAINED_GLASS(15, "STAINED_GLASS"),
    BLACK_STAINED_GLASS_PANE(15, "STAINED_GLASS_PANE"),
    BLACK_TERRACOTTA(15, "HARD_CLAY", "STAINED_CLAY"),
    BLACK_WALL_BANNER(0, "WALL_BANNER"),
    BLACK_WOOL(15, "WOOL"),
    BLAST_FURNACE(0, "1.14", "FURNACE"),
    BLAZE_POWDER(0, ""),
    BLAZE_ROD(0, ""),
    BLAZE_SPAWN_EGG(61, "MONSTER_EGG"),
    BLUE_BANNER(11, "BANNER", "STANDING_BANNER"),
    BLUE_BED(4, "BED", "BED_BLOCK"),
    BLUE_CARPET(11, "CARPET"),
    BLUE_CONCRETE(11, "CONCRETE"),
    BLUE_CONCRETE_POWDER(11, "CONCRETE_POWDER"),
    BLUE_DYE(4, "INK_SACK", "LAPIS_LAZULI"),
    BLUE_GLAZED_TERRACOTTA(11, "1.12", "HARD_CLAY", "STAINED_CLAY", "BLUE_TERRACOTTA"),
    BLUE_ICE(0, "1.13", "PACKED_ICE"),
    BLUE_ORCHID(1, "RED_ROSE"),
    BLUE_SHULKER_BOX(0, ""),
    BLUE_STAINED_GLASS(11, "STAINED_GLASS"),
    BLUE_STAINED_GLASS_PANE(11, "THIN_GLASS", "STAINED_GLASS_PANE"),
    BLUE_TERRACOTTA(11, "STAINED_CLAY"),
    BLUE_WALL_BANNER(11, "WALL_BANNER"),
    BLUE_WOOL(11, "WOOL"),
    BONE(0, ""),
    BONE_BLOCK(0, ""),
    BONE_MEAL(15, "INK_SACK"),
    BOOK(0, ""),
    BOOKSHELF(0, ""),
    BOW(0, ""),
    BOWL(0, ""),
    BRAIN_CORAL(0, "1.13"),
    BRAIN_CORAL_BLOCK(0, "1.13"),
    BRAIN_CORAL_FAN(0, "1.13"),
    BRAIN_CORAL_WALL_FAN(0, ""),
    BREAD(0, ""),
    BREWING_STAND(0, "BREWING_STAND_ITEM"),
    BRICK(0, "CLAY_BRICK"),
    BRICKS(0, "BRICK"),
    BRICK_SLAB(4, "STEP"),
    BRICK_STAIRS(0, ""),
    BRICK_WALL(0, ""),
    BROWN_BANNER(3, "BANNER", "STANDING_BANNER"),
    BROWN_BED(12, "BED", "BED_BLOCK"),
    BROWN_DYE(3, "INK_SACK", "COCOA", "COCOA_BEANS"),
    BROWN_CARPET(12, "CARPET"),
    BROWN_CONCRETE(12, "CONCRETE"),
    BROWN_CONCRETE_POWDER(12, "CONCRETE_POWDER"),
    BROWN_GLAZED_TERRACOTTA(12, "1.12", "HARD_CLAY", "STAINED_CLAY", "BROWN_TERRACOTTA"),
    BROWN_MUSHROOM(0, ""),
    BROWN_MUSHROOM_BLOCK(0, "BROWN_MUSHROOM", "HUGE_MUSHROOM_1"),
    BROWN_SHULKER_BOX(0, ""),
    BROWN_STAINED_GLASS(12, "STAINED_GLASS"),
    BROWN_STAINED_GLASS_PANE(12, "THIN_GLASS", "STAINED_GLASS_PANE"),
    BROWN_TERRACOTTA(12, "STAINED_CLAY"),
    BROWN_WALL_BANNER(3, "WALL_BANNER"),
    BROWN_WOOL(12, "WOOL"),
    BUBBLE_COLUMN(0, "1.13"),
    BUBBLE_CORAL(0, "1.13"),
    BUBBLE_CORAL_BLOCK(0, "1.13"),
    BUBBLE_CORAL_FAN(0, "1.13"),
    BUBBLE_CORAL_WALL_FAN(0, ""),
    BUCKET(0, ""),
    CACTUS(0, ""),
    CAKE(0, "CAKE_BLOCK"),
    CAMPFIRE(0, "1.14"),
    CARROT(0, "CARROT_ITEM"),
    CARROTS(0, "CARROT"),
    CARROT_ON_A_STICK(0, "CARROT_STICK"),
    CARTOGRAPHY_TABLE(0, "1.14", "CRAFTING_TABLE"),
    CARVED_PUMPKIN(1, "PUMPKIN"),
    CAT_SPAWN_EGG(0, ""),
    CAULDRON(0, "CAULDRON_ITEM"),
    CAVE_AIR(0, "AIR"),
    CAVE_SPIDER_SPAWN_EGG(59, "MONSTER_EGG"),
    CHAINMAIL_BOOTS(0, ""),
    CHAINMAIL_CHESTPLATE(0, ""),
    CHAINMAIL_HELMET(0, ""),
    CHAINMAIL_LEGGINGS(0, ""),
    CHAIN_COMMAND_BLOCK(0, "COMMAND", "COMMAND_CHAIN"),
    CHARCOAL(1, "COAL"),
    CHEST(0, "LOCKED_CHEST"),
    CHEST_MINECART(0, "STORAGE_MINECART"),
    CHICKEN(0, "RAW_CHICKEN"),
    CHICKEN_SPAWN_EGG(93, "MONSTER_EGG"),
    CHIPPED_ANVIL(1, "ANVIL"),
    CHISELED_QUARTZ_BLOCK(1, "QUARTZ_BLOCK"),
    CHISELED_RED_SANDSTONE(1, "RED_SANDSTONE"),
    CHISELED_SANDSTONE(1, "SANDSTONE"),
    CHISELED_STONE_BRICKS(3, "SMOOTH_BRICK"),
    CHORUS_FLOWER(0, ""),
    CHORUS_FRUIT(0, ""),
    CHORUS_PLANT(0, ""),
    CLAY(0, ""),
    CLAY_BALL(0, ""),
    CLOCK(0, "WATCH"),
    COAL(0, ""),
    COAL_BLOCK(0, ""),
    COAL_ORE(0, ""),
    COARSE_DIRT(1, "DIRT"),
    COBBLESTONE(0, ""),
    COBBLESTONE_SLAB(3, "STEP"),
    COBBLESTONE_STAIRS(0, ""),
    COBBLESTONE_WALL(0, "COBBLE_WALL"),
    COBWEB(0, "WEB"),
    COCOA_BEANS(3, "INK_SACK", "COCOA"),
    COD(0, "RAW_FISH"),
    COD_BUCKET(0, "1.13", "BUCKET", "WATER_BUCKET"),
    COD_SPAWN_EGG(0, "1.13", "MONSTER_EGG"),
    COMMAND_BLOCK(0, "COMMAND"),
    COMMAND_BLOCK_MINECART(0, "COMMAND_MINECART"),
    COMPARATOR(0, "REDSTONE_COMPARATOR", "REDSTONE_COMPARATOR_ON", "REDSTONE_COMPARATOR_OFF"),
    COMPASS(0, ""),
    COMPOSTER(0, "1.14", "CAULDRON"),
    CONDUIT(0, "1.13"),
    COOKED_BEEF(0, ""),
    COOKED_CHICKEN(0, ""),
    COOKED_COD(0, "COOKED_FISH"),
    COOKED_MUTTON(0, ""),
    COOKED_PORKCHOP(0, "PORK", "GRILLED_PORK"),
    COOKED_RABBIT(0, ""),
    COOKED_SALMON(1, "COOKED_FISH"),
    COOKIE(0, ""),
    CORNFLOWER(4, "1.14", "BLUE_DYE"),
    COW_SPAWN_EGG(92, "MONSTER_EGG"),
    CRACKED_STONE_BRICKS(2, "SMOOTH_BRICK"),
    CRAFTING_TABLE(0, "WORKBENCH"),
    CREEPER_BANNER_PATTERN(0, ""),
    CREEPER_HEAD(4, "SKULL", "SKULL_ITEM"),
    CREEPER_SPAWN_EGG(50, "MONSTER_EGG"),
    CREEPER_WALL_HEAD(4, "SKULL", "SKULL_ITEM"),
    CROSSBOW(0, ""),
    CUT_RED_SANDSTONE(0, "1.13"),
    CUT_RED_SANDSTONE_SLAB(0, "STONE_SLAB2"),
    CUT_SANDSTONE(0, "1.13"),
    CUT_SANDSTONE_SLAB(0, "STEP"),
    CYAN_BANNER(6, "BANNER", "STANDING_BANNER"),
    CYAN_BED(9, "BED", "BED_BLOCK"),
    CYAN_CARPET(9, "CARPET"),
    CYAN_CONCRETE(9, "CONCRETE"),
    CYAN_CONCRETE_POWDER(9, "CONCRETE_POWDER"),
    CYAN_DYE(6, "INK_SACK"),
    CYAN_GLAZED_TERRACOTTA(9, "1.12", "HARD_CLAY", "STAINED_CLAY", "CYAN_TERRACOTTA"),
    CYAN_SHULKER_BOX(0, ""),
    CYAN_STAINED_GLASS(9, "STAINED_GLASS"),
    CYAN_STAINED_GLASS_PANE(9, "STAINED_GLASS_PANE"),
    CYAN_TERRACOTTA(9, "HARD_CLAY", "STAINED_CLAY"),
    CYAN_WALL_BANNER(6, "WALL_BANNER"),
    CYAN_WOOL(9, "WOOL"),
    DAMAGED_ANVIL(2, "ANVIL"),
    DANDELION(0, "YELLOW_FLOWER"),
    DARK_OAK_BOAT(0, "BOAT_DARK_OAK"),
    DARK_OAK_BUTTON(0, "WOOD_BUTTON"),
    DARK_OAK_DOOR(0, "DARK_OAK_DOOR_ITEM"),
    DARK_OAK_FENCE(0, ""),
    DARK_OAK_FENCE_GATE(0, ""),
    DARK_OAK_LEAVES(1, "LEAVES", "LEAVES_2"),
    DARK_OAK_LOG(1, "LOG", "LOG_2"),
    DARK_OAK_PLANKS(5, "WOOD"),
    DARK_OAK_PRESSURE_PLATE(0, "WOOD_PLATE"),
    DARK_OAK_SAPLING(5, "SAPLING"),
    DARK_OAK_SIGN(0, "SIGN"),
    DARK_OAK_SLAB(0, "WOOD_STEP", "WOODEN_SLAB", "WOOD_DOUBLE_STEP"),
    DARK_OAK_STAIRS(0, ""),
    DARK_OAK_TRAPDOOR(0, "TRAP_DOOR"),
    DARK_OAK_WALL_SIGN(0, "SIGN_POST", "WALL_SIGN"),
    DARK_OAK_WOOD(1, "LOG", "LOG_2"),
    DARK_PRISMARINE(1, "PRISMARINE"),
    DARK_PRISMARINE_SLAB(0, "1.13"),
    DARK_PRISMARINE_STAIRS(0, "1.13"),
    DAYLIGHT_DETECTOR(0, "DAYLIGHT_DETECTOR_INVERTED"),
    DEAD_BRAIN_CORAL(0, ""),
    DEAD_BRAIN_CORAL_BLOCK(0, "1.13"),
    DEAD_BRAIN_CORAL_FAN(0, ""),
    DEAD_BRAIN_CORAL_WALL_FAN(0, ""),
    DEAD_BUBBLE_CORAL(0, ""),
    DEAD_BUBBLE_CORAL_BLOCK(0, "1.13"),
    DEAD_BUBBLE_CORAL_FAN(0, ""),
    DEAD_BUBBLE_CORAL_WALL_FAN(0, ""),
    DEAD_BUSH(0, ""),
    DEAD_FIRE_CORAL(0, ""),
    DEAD_FIRE_CORAL_BLOCK(0, "1.13"),
    DEAD_FIRE_CORAL_FAN(0, ""),
    DEAD_FIRE_CORAL_WALL_FAN(0, ""),
    DEAD_HORN_CORAL(0, ""),
    DEAD_HORN_CORAL_BLOCK(0, "1.13"),
    DEAD_HORN_CORAL_FAN(0, ""),
    DEAD_HORN_CORAL_WALL_FAN(0, ""),
    DEAD_TUBE_CORAL(0, ""),
    DEAD_TUBE_CORAL_BLOCK(0, "1.13"),
    DEAD_TUBE_CORAL_FAN(0, ""),
    DEAD_TUBE_CORAL_WALL_FAN(0, ""),
    DEBUG_STICK(0, "1.13", "STICK"),
    DETECTOR_RAIL(0, ""),
    DIAMOND(0, ""),
    DIAMOND_AXE(0, ""),
    DIAMOND_BLOCK(0, ""),
    DIAMOND_BOOTS(0, ""),
    DIAMOND_CHESTPLATE(0, ""),
    DIAMOND_HELMET(0, ""),
    DIAMOND_HOE(0, ""),
    DIAMOND_HORSE_ARMOR(0, "DIAMOND_BARDING"),
    DIAMOND_LEGGINGS(0, ""),
    DIAMOND_ORE(0, ""),
    DIAMOND_PICKAXE(0, ""),
    DIAMOND_SHOVEL(0, "DIAMOND_SPADE"),
    DIAMOND_SWORD(0, ""),
    DIORITE(3, "1.13"),
    DIORITE_SLAB(0, ""),
    DIORITE_STAIRS(0, ""),
    DIORITE_WALL(0, ""),
    DIRT(0, ""),
    DISPENSER(0, ""),
    DOLPHIN_SPAWN_EGG(0, "1.13", "MONSTER_EGG"),
    DONKEY_SPAWN_EGG(32, "MONSTER_EGG"),
    DRAGON_BREATH(0, "DRAGONS_BREATH"),
    DRAGON_EGG(0, ""),
    DRAGON_HEAD(5, "SKULL", "SKULL_ITEM"),
    DRAGON_WALL_HEAD(5, "SKULL", "SKULL_ITEM"),
    DRIED_KELP(0, "1.13"),
    DRIED_KELP_BLOCK(0, "1.13"),
    DROPPER(0, ""),
    DROWNED_SPAWN_EGG(0, "1.13", "MONSTER_EGG"),
    EGG(0, ""),
    ELDER_GUARDIAN_SPAWN_EGG(4, "MONSTER_EGG"),
    ELYTRA(0, ""),
    EMERALD(0, ""),
    EMERALD_BLOCK(0, ""),
    EMERALD_ORE(0, ""),
    ENCHANTED_BOOK(0, ""),
    ENCHANTED_GOLDEN_APPLE(1, "GOLDEN_APPLE"),
    ENCHANTING_TABLE(0, "ENCHANTMENT_TABLE"),
    ENDERMAN_SPAWN_EGG(58, "MONSTER_EGG"),
    ENDERMITE_SPAWN_EGG(67, "MONSTER_EGG"),
    ENDER_CHEST(0, ""),
    ENDER_EYE(0, "EYE_OF_ENDER"),
    ENDER_PEARL(0, ""),
    END_CRYSTAL(0, ""),
    END_GATEWAY(0, ""),
    END_PORTAL(0, "ENDER_PORTAL"),
    END_PORTAL_FRAME(0, "ENDER_PORTAL_FRAME"),
    END_ROD(0, ""),
    END_STONE(0, "ENDER_STONE"),
    END_STONE_BRICKS(0, "END_BRICKS"),
    END_STONE_BRICK_SLAB(4, "STEP"),
    END_STONE_BRICK_STAIRS(0, "SMOOTH_STAIRS"),
    END_STONE_BRICK_WALL(0, ""),
    EVOKER_SPAWN_EGG(34, "MONSTER_EGG"),
    EXPERIENCE_BOTTLE(0, "EXP_BOTTLE"),
    FARMLAND(0, "SOIL"),
    FEATHER(0, ""),
    FERMENTED_SPIDER_EYE(0, ""),
    FERN(2, "LONG_GRASS"),
    FILLED_MAP(0, "MAP"),
    FIRE(0, ""),
    FIREWORK_ROCKET(0, "FIREWORK"),
    FIREWORK_STAR(0, "FIREWORK_CHARGE"),
    FIRE_CHARGE(0, "FIREBALL"),
    FIRE_CORAL(0, "1.13"),
    FIRE_CORAL_BLOCK(0, "1.13"),
    FIRE_CORAL_FAN(0, "1.13"),
    FIRE_CORAL_WALL_FAN(0, ""),
    FISHING_ROD(0, ""),
    FLETCHING_TABLE(0, "1.14", "CRAFTING_TABLE"),
    FLINT(0, ""),
    FLINT_AND_STEEL(0, ""),
    FLOWER_BANNER_PATTERN(0, ""),
    FLOWER_POT(0, "FLOWER_POT_ITEM"),
    FOX_SPAWN_EGG(0, "1.14"),
    FROSTED_ICE(0, ""),
    FURNACE(0, "BURNING_FURNACE"),
    FURNACE_MINECART(0, "POWERED_MINECART"),
    GHAST_SPAWN_EGG(56, "MONSTER_EGG"),
    GHAST_TEAR(0, ""),
    GLASS(0, ""),
    GLASS_BOTTLE(0, ""),
    GLASS_PANE(0, "THIN_GLASS"),
    GLISTERING_MELON_SLICE(0, "SPECKLED_MELON"),
    GLOBE_BANNER_PATTERN(0, ""),
    GLOWSTONE(0, ""),
    GLOWSTONE_DUST(0, ""),
    GOLDEN_APPLE(0, ""),
    GOLDEN_AXE(0, "GOLD_AXE"),
    GOLDEN_BOOTS(0, "GOLD_BOOTS"),
    GOLDEN_CARROT(0, ""),
    GOLDEN_CHESTPLATE(0, "GOLD_CHESTPLATE"),
    GOLDEN_HELMET(0, "GOLD_HELMET"),
    GOLDEN_HOE(0, "GOLD_HOE"),
    GOLDEN_HORSE_ARMOR(0, "GOLD_BARDING"),
    GOLDEN_LEGGINGS(0, "GOLD_LEGGINGS"),
    GOLDEN_PICKAXE(0, "GOLD_PICKAXE"),
    GOLDEN_SHOVEL(0, "GOLD_SPADE"),
    GOLDEN_SWORD(0, "GOLD_SWORD"),
    GOLD_BLOCK(0, ""),
    GOLD_INGOT(0, ""),
    GOLD_NUGGET(0, ""),
    GOLD_ORE(0, ""),
    GRANITE(1, "1.13"),
    GRANITE_SLAB(0, ""),
    GRANITE_STAIRS(0, ""),
    GRANITE_WALL(0, ""),
    GRASS(0, ""),
    GRASS_BLOCK(0, "GRASS"),
    GRASS_PATH(0, ""),
    GRAVEL(0, ""),
    GRAY_BANNER(8, "BANNER", "STANDING_BANNER"),
    GRAY_BED(7, "BED", "BED_BLOCK"),
    GRAY_CARPET(7, "CARPET"),
    GRAY_CONCRETE(7, "CONCRETE"),
    GRAY_CONCRETE_POWDER(7, "CONCRETE_POWDER"),
    GRAY_DYE(8, "INK_SACK"),
    GRAY_GLAZED_TERRACOTTA(7, "1.12", "HARD_CLAY", "STAINED_CLAY", "GRAY_TERRACOTTA"),
    GRAY_SHULKER_BOX(0, ""),
    GRAY_STAINED_GLASS(8, "STAINED_GLASS"),
    GRAY_STAINED_GLASS_PANE(7, "THIN_GLASS", "STAINED_GLASS_PANE"),
    GRAY_TERRACOTTA(7, "HARD_CLAY", "STAINED_CLAY"),
    GRAY_WALL_BANNER(8, "WALL_BANNER"),
    GRAY_WOOL(8, "WOOL"),
    GREEN_BANNER(2, "BANNER", "STANDING_BANNER"),
    GREEN_BED(13, "BED", "BED_BLOCK"),
    GREEN_CARPET(13, "CARPET"),
    GREEN_CONCRETE(13, "CONCRETE"),
    GREEN_CONCRETE_POWDER(13, "CONCRETE_POWDER"),
    GREEN_DYE(2, "INK_SACK", "CACTUS_GREEN"),
    GREEN_GLAZED_TERRACOTTA(13, "1.12", "HARD_CLAY", "STAINED_CLAY", "GREEN_TERRACOTTA"),
    GREEN_SHULKER_BOX(0, ""),
    GREEN_STAINED_GLASS(13, "STAINED_GLASS"),
    GREEN_STAINED_GLASS_PANE(13, "THIN_GLASS", "STAINED_GLASS_PANE"),
    GREEN_TERRACOTTA(13, "HARD_CLAY", "STAINED_CLAY"),
    GREEN_WALL_BANNER(2, "WALL_BANNER"),
    GREEN_WOOL(13, "WOOL"),
    GRINDSTONE(0, "1.14", "ANVIL"),
    GUARDIAN_SPAWN_EGG(68, "MONSTER_EGG"),
    GUNPOWDER(0, "SULPHUR"),
    HAY_BLOCK(0, ""),
    HEART_OF_THE_SEA(0, "1.13"),
    HEAVY_WEIGHTED_PRESSURE_PLATE(0, "IRON_PLATE"),
    HOPPER(0, ""),
    HOPPER_MINECART(0, ""),
    HORN_CORAL(0, "1.13"),
    HORN_CORAL_BLOCK(0, "1.13"),
    HORN_CORAL_FAN(0, "1.13"),
    HORN_CORAL_WALL_FAN(0, ""),
    HORSE_SPAWN_EGG(100, "MONSTER_EGG"),
    HUSK_SPAWN_EGG(23, "MONSTER_EGG"),
    ICE(0, ""),
    INFESTED_CHISELED_STONE_BRICKS(5, "MONSTER_EGGS", "SMOOTH_BRICK"),
    INFESTED_COBBLESTONE(1, "MONSTER_EGGS"),
    INFESTED_CRACKED_STONE_BRICKS(4, "MONSTER_EGGS", "SMOOTH_BRICK"),
    INFESTED_MOSSY_STONE_BRICKS(3, "MONSTER_EGGS"),
    INFESTED_STONE(0, "MONSTER_EGGS"),
    INFESTED_STONE_BRICKS(2, "MONSTER_EGGS", "SMOOTH_BRICK"),
    INK_SAC(0, "INK_SACK"),
    IRON_AXE(0, ""),
    IRON_BARS(0, "IRON_FENCE"),
    IRON_BLOCK(0, ""),
    IRON_BOOTS(0, ""),
    IRON_CHESTPLATE(0, ""),
    IRON_DOOR(0, "IRON_DOOR_BLOCK"),
    IRON_HELMET(0, ""),
    IRON_HOE(0, ""),
    IRON_HORSE_ARMOR(0, "IRON_BARDING"),
    IRON_INGOT(0, ""),
    IRON_LEGGINGS(0, ""),
    IRON_NUGGET(0, ""),
    IRON_ORE(0, ""),
    IRON_PICKAXE(0, ""),
    IRON_SHOVEL(0, "IRON_SPADE"),
    IRON_SWORD(0, ""),
    IRON_TRAPDOOR(0, ""),
    ITEM_FRAME(0, ""),
    JACK_O_LANTERN(0, ""),
    JIGSAW(0, "1.14", "COMMAND_BLOCK", "STRUCTURE_BLOCK"),
    JUKEBOX(0, ""),
    JUNGLE_BOAT(0, "BOAT_JUNGLE"),
    JUNGLE_BUTTON(0, "WOOD_BUTTON"),
    JUNGLE_DOOR(0, "JUNGLE_DOOR_ITEM"),
    JUNGLE_FENCE(0, ""),
    JUNGLE_FENCE_GATE(0, ""),
    JUNGLE_LEAVES(3, "LEAVES"),
    JUNGLE_LOG(3, "LOG"),
    JUNGLE_PLANKS(3, "WOOD"),
    JUNGLE_PRESSURE_PLATE(0, "WOOD_PLATE"),
    JUNGLE_SAPLING(3, "SAPLING"),
    JUNGLE_SIGN(0, "SIGN"),
    JUNGLE_SLAB(3, "WOOD_STEP", "WOODEN_SLAB", "WOOD_DOUBLE_STEP"),
    JUNGLE_STAIRS(0, "JUNGLE_WOOD_STAIRS"),
    JUNGLE_TRAPDOOR(0, "TRAP_DOOR"),
    JUNGLE_WALL_SIGN(0, "SIGN_POST", "WALL_SIGN"),
    JUNGLE_WOOD(3, "LOG"),
    KELP(0, "1.13"),
    KELP_PLANT(0, "1.13"),
    KNOWLEDGE_BOOK(0, ""),
    LADDER(0, ""),
    LANTERN(0, "1.14", "SEA_LANTERN"),
    LAPIS_BLOCK(0, ""),
    LAPIS_LAZULI(4, "INK_SACK"),
    LAPIS_ORE(0, ""),
    LARGE_FERN(3, "DOUBLE_PLANT"),
    LAVA(0, "STATIONARY_LAVA"),
    LAVA_BUCKET(0, ""),
    LEAD(0, "LEASH"),
    LEATHER(0, ""),
    LEATHER_BOOTS(0, ""),
    LEATHER_CHESTPLATE(0, ""),
    LEATHER_HELMET(0, ""),
    LEATHER_HORSE_ARMOR(0, "1.14", "IRON_HORSE_ARMOR"),
    LEATHER_LEGGINGS(0, ""),
    LECTERN(0, "1.14", "BOOKSHELF"),
    LEVER(0, ""),
    LIGHT_BLUE_BANNER(11, "BANNER", "STANDING_BANNER"),
    LIGHT_BLUE_BED(3, "BED", "BED_BLOCK"),
    LIGHT_BLUE_CARPET(3, "CARPET"),
    LIGHT_BLUE_CONCRETE(3, "CONCRETE"),
    LIGHT_BLUE_CONCRETE_POWDER(3, "CONCRETE_POWDER"),
    LIGHT_BLUE_DYE(12, "INK_SACK"),
    LIGHT_BLUE_GLAZED_TERRACOTTA(3, "1.12", "HARD_CLAY", "STAINED_CLAY", "LIGHT_BLUE_TERRACOTTA"),
    LIGHT_BLUE_SHULKER_BOX(0, ""),
    LIGHT_BLUE_STAINED_GLASS(11, "STAINED_GLASS"),
    LIGHT_BLUE_STAINED_GLASS_PANE(3, "THIN_GLASS", "STAINED_GLASS_PANE"),
    LIGHT_BLUE_TERRACOTTA(3, "STAINED_CLAY"),
    LIGHT_BLUE_WALL_BANNER(12, "WALL_BANNER", "BANNER", "STANDING_BANNER"),
    LIGHT_BLUE_WOOL(11, "WOOL"),
    LIGHT_GRAY_BANNER(7, "BANNER", "STANDING_BANNER"),
    LIGHT_GRAY_BED(7, "BED", "BED_BLOCK"),
    LIGHT_GRAY_CARPET(8, "CARPET"),
    LIGHT_GRAY_CONCRETE(8, "CONCRETE"),
    LIGHT_GRAY_CONCRETE_POWDER(8, "CONCRETE_POWDER"),
    LIGHT_GRAY_DYE(7, "INK_SACK"),
    LIGHT_GRAY_GLAZED_TERRACOTTA(8, "1.12", "HARD_CLAY", "STAINED_CLAY", "LIGHT_GRAY_TERRACOTTA", "SILVER_GLAZED_TERRACOTTA/1.13"),
    LIGHT_GRAY_SHULKER_BOX(0, "SILVER_SHULKER_BOX"),
    LIGHT_GRAY_STAINED_GLASS(8, "STAINED_GLASS"),
    LIGHT_GRAY_STAINED_GLASS_PANE(8, "THIN_GLASS", "STAINED_GLASS_PANE"),
    LIGHT_GRAY_TERRACOTTA(8, "HARD_CLAY", "STAINED_CLAY"),
    LIGHT_GRAY_WALL_BANNER(7, "WALL_BANNER"),
    LIGHT_GRAY_WOOL(8, "WOOL"),
    LIGHT_WEIGHTED_PRESSURE_PLATE(0, "GOLD_PLATE"),
    LILAC(1, "DOUBLE_PLANT"),
    LILY_OF_THE_VALLEY(15, "1.14", "WHITE_DYE"),
    LILY_PAD(0, "WATER_LILY"),
    LIME_BANNER(10, "BANNER", "STANDING_BANNER"),
    LIME_BED(5, "BED", "BED_BLOCK"),
    LIME_CARPET(5, "CARPET"),
    LIME_CONCRETE(5, "CONCRETE"),
    LIME_CONCRETE_POWDER(5, "CONCRETE_POWDER"),
    LIME_DYE(10, "INK_SACK"),
    LIME_GLAZED_TERRACOTTA(5, "1.12", "HARD_CLAY", "STAINED_CLAY", "LIME_TERRACOTTA"),
    LIME_SHULKER_BOX(0, ""),
    LIME_STAINED_GLASS(5, "STAINED_GLASS"),
    LIME_STAINED_GLASS_PANE(5, "STAINED_GLASS_PANE"),
    LIME_TERRACOTTA(5, "HARD_CLAY", "STAINED_CLAY"),
    LIME_WALL_BANNER(10, "WALL_BANNER"),
    LIME_WOOL(5, "WOOL"),
    LINGERING_POTION(0, ""),
    LLAMA_SPAWN_EGG(103, "MONSTER_EGG"),
    LOOM(0, "1.14"),
    MAGENTA_BANNER(13, "BANNER", "STANDING_BANNER"),
    MAGENTA_BED(2, "BED", "BED_BLOCK"),
    MAGENTA_CARPET(2, "CARPET"),
    MAGENTA_CONCRETE(2, "CONCRETE"),
    MAGENTA_CONCRETE_POWDER(2, "CONCRETE_POWDER"),
    MAGENTA_DYE(13, "INK_SACK"),
    MAGENTA_GLAZED_TERRACOTTA(2, "1.12", "HARD_CLAY", "STAINED_CLAY", "MAGENTA_TERRACOTTA"),
    MAGENTA_SHULKER_BOX(0, ""),
    MAGENTA_STAINED_GLASS(2, "STAINED_GLASS"),
    MAGENTA_STAINED_GLASS_PANE(2, "THIN_GLASS", "STAINED_GLASS_PANE"),
    MAGENTA_TERRACOTTA(2, "HARD_CLAY", "STAINED_CLAY"),
    MAGENTA_WALL_BANNER(13, "WALL_BANNER"),
    MAGENTA_WOOL(2, "WOOL"),
    MAGMA_BLOCK(0, "MAGMA"),
    MAGMA_CREAM(0, ""),
    MAGMA_CUBE_SPAWN_EGG(62, "MONSTER_EGG"),
    MAP(0, "EMPTY_MAP"),
    MELON(0, "MELON_BLOCK"),
    MELON_SEEDS(0, ""),
    MELON_SLICE(0, "MELON"),
    MELON_STEM(0, ""),
    MILK_BUCKET(0, ""),
    MINECART(0, ""),
    MOJANG_BANNER_PATTERN(0, ""),
    MOOSHROOM_SPAWN_EGG(96, "MONSTER_EGG"),
    MOSSY_COBBLESTONE(0, ""),
    MOSSY_COBBLESTONE_SLAB(3, "STEP"),
    MOSSY_COBBLESTONE_STAIRS(0, ""),
    MOSSY_COBBLESTONE_WALL(1, "COBBLE_WALL", "COBBLESTONE_WALL"),
    MOSSY_STONE_BRICKS(1, "SMOOTH_BRICK"),
    MOSSY_STONE_BRICK_SLAB(4, "STEP"),
    MOSSY_STONE_BRICK_STAIRS(0, "SMOOTH_STAIRS"),
    MOSSY_STONE_BRICK_WALL(0, ""),
    MOVING_PISTON(0, "PISTON_BASE", "PISTON_MOVING_PIECE"),
    MULE_SPAWN_EGG(32, "MONSTER_EGG"),
    MUSHROOM_STEM(0, "BROWN_MUSHROOM"),
    MUSHROOM_STEW(0, "MUSHROOM_SOUP"),
    MUSIC_DISC_11(0, "GOLD_RECORD"),
    MUSIC_DISC_13(0, "GREEN_RECORD"),
    MUSIC_DISC_BLOCKS(0, "RECORD_3"),
    MUSIC_DISC_CAT(0, "RECORD_4"),
    MUSIC_DISC_CHIRP(0, "RECORD_5"),
    MUSIC_DISC_FAR(0, "RECORD_6"),
    MUSIC_DISC_MALL(0, "RECORD_7"),
    MUSIC_DISC_MELLOHI(0, "RECORD_8"),
    MUSIC_DISC_STAL(0, "RECORD_9"),
    MUSIC_DISC_STRAD(0, "RECORD_10"),
    MUSIC_DISC_WAIT(0, "RECORD_11"),
    MUSIC_DISC_WARD(0, "RECORD_12"),
    MUTTON(0, ""),
    MYCELIUM(0, "MYCEL"),
    NAME_TAG(0, ""),
    NAUTILUS_SHELL(0, "1.13"),
    NETHERRACK(0, ""),
    NETHER_BRICK(0, "NETHER_BRICK_ITEM"),
    NETHER_BRICKS(0, "NETHER_BRICK"),
    NETHER_BRICK_FENCE(0, "NETHER_FENCE"),
    NETHER_BRICK_SLAB(4, "STEP"),
    NETHER_BRICK_STAIRS(0, ""),
    NETHER_BRICK_WALL(0, ""),
    NETHER_PORTAL(0, "PORTAL"),
    NETHER_QUARTZ_ORE(0, "QUARTZ_ORE"),
    NETHER_STAR(0, ""),
    NETHER_WART(0, "NETHER_STALK"),
    NETHER_WART_BLOCK(0, "NETHER_WARTS"),
    NOTE_BLOCK(0, ""),
    OAK_BOAT(0, "BOAT"),
    OAK_BUTTON(0, "WOOD_BUTTON"),
    OAK_DOOR(0, "WOOD_DOOR", "WOODEN_DOOR"),
    OAK_FENCE(0, "FENCE"),
    OAK_FENCE_GATE(0, "FENCE_GATE"),
    OAK_LEAVES(0, "LEAVES"),
    OAK_LOG(0, "LOG"),
    OAK_PLANKS(0, "WOOD"),
    OAK_PRESSURE_PLATE(0, "WOOD_PLATE"),
    OAK_SAPLING(0, "SAPLING"),
    OAK_SIGN(0, "SIGN"),
    OAK_SLAB(0, "WOOD_STEP", "WOODEN_SLAB", "WOOD_DOUBLE_STEP"),
    OAK_STAIRS(0, "WOOD_STAIRS"),
    OAK_TRAPDOOR(0, "TRAP_DOOR"),
    OAK_WALL_SIGN(0, "SIGN_POST", "WALL_SIGN"),
    OAK_WOOD(0, "LOG"),
    OBSERVER(0, ""),
    OBSIDIAN(0, ""),
    OCELOT_SPAWN_EGG(98, "MONSTER_EGG"),
    ORANGE_BANNER(14, "BANNER", "STANDING_BANNER"),
    ORANGE_BED(1, "BED", "BED_BLOCK"),
    ORANGE_CARPET(1, "CARPET"),
    ORANGE_CONCRETE(1, "CONCRETE"),
    ORANGE_CONCRETE_POWDER(1, "CONCRETE_POWDER"),
    ORANGE_DYE(14, "INK_SACK"),
    ORANGE_GLAZED_TERRACOTTA(1, "1.12", "HARD_CLAY", "STAINED_CLAY", "ORANGE_TERRACOTTA"),
    ORANGE_SHULKER_BOX(0, ""),
    ORANGE_STAINED_GLASS(1, "STAINED_GLASS"),
    ORANGE_STAINED_GLASS_PANE(1, "STAINED_GLASS_PANE"),
    ORANGE_TERRACOTTA(1, "HARD_CLAY", "STAINED_CLAY"),
    ORANGE_TULIP(5, "RED_ROSE"),
    ORANGE_WALL_BANNER(14, "WALL_BANNER"),
    ORANGE_WOOL(1, "WOOL"),
    OXEYE_DAISY(8, "RED_ROSE"),
    PACKED_ICE(0, ""),
    PAINTING(0, ""),
    PANDA_SPAWN_EGG(0, "1.14"),
    PAPER(0, ""),
    PARROT_SPAWN_EGG(105, "MONSTER_EGG"),
    PEONY(5, "DOUBLE_PLANT"),
    PETRIFIED_OAK_SLAB(0, "WOOD_STEP"),
    PHANTOM_MEMBRANE(0, "1.13"),
    PHANTOM_SPAWN_EGG(0, "1.13", "MONSTER_EGG"),
    PIG_SPAWN_EGG(90, "MONSTER_EGG"),
    PILLAGER_SPAWN_EGG(0, "1.14"),
    PINK_BANNER(9, "BANNER", "STANDING_BANNER"),
    PINK_BED(6, "BED", "BED_BLOCK"),
    PINK_CARPET(6, "CARPET"),
    PINK_CONCRETE(6, "CONCRETE"),
    PINK_CONCRETE_POWDER(6, "CONCRETE_POWDER"),
    PINK_DYE(9, "INK_SACK"),
    PINK_GLAZED_TERRACOTTA(6, "1.12", "HARD_CLAY", "STAINED_CLAY", "PINK_TERRACOTTA"),
    PINK_SHULKER_BOX(0, ""),
    PINK_STAINED_GLASS(6, "STAINED_GLASS"),
    PINK_STAINED_GLASS_PANE(6, "THIN_GLASS", "STAINED_GLASS_PANE"),
    PINK_TERRACOTTA(6, "HARD_CLAY", "STAINED_CLAY"),
    PINK_TULIP(7, "RED_ROSE"),
    PINK_WALL_BANNER(14, "WALL_BANNER"),
    PINK_WOOL(6, "WOOL"),
    PISTON(0, "PISTON_BASE"),
    PISTON_HEAD(0, "PISTON_EXTENSION"),
    PLAYER_HEAD(3, "SKULL", "SKULL_ITEM"),
    PLAYER_WALL_HEAD(3, "SKULL", "SKULL_ITEM"),
    PODZOL(2, "DIRT"),
    POISONOUS_POTATO(0, ""),
    POLAR_BEAR_SPAWN_EGG(102, "MONSTER_EGG"),
    POLISHED_ANDESITE(6, "1.13"),
    POLISHED_ANDESITE_SLAB(0, ""),
    POLISHED_ANDESITE_STAIRS(0, ""),
    POLISHED_DIORITE(4, "1.13"),
    POLISHED_DIORITE_SLAB(0, ""),
    POLISHED_DIORITE_STAIRS(0, ""),
    POLISHED_GRANITE(2, "1.13"),
    POLISHED_GRANITE_SLAB(0, ""),
    POLISHED_GRANITE_STAIRS(0, ""),
    POPPED_CHORUS_FRUIT(0, "CHORUS_FRUIT_POPPED"),
    POPPY(0, "RED_ROSE"),
    PORKCHOP(0, "PORK"),
    POTATO(0, "POTATO_ITEM"),
    POTATOES(0, "POTATO"),
    POTION(0, ""),
    POTTED_ACACIA_SAPLING(4, "SAPLING", "FLOWER_POT"),
    POTTED_ALLIUM(2, "RED_ROSE", "FLOWER_POT"),
    POTTED_AZURE_BLUET(3, "RED_ROSE", "FLOWER_POT"),
    POTTED_BAMBOO(0, ""),
    POTTED_BIRCH_SAPLING(2, "SAPLING", "FLOWER_POT"),
    POTTED_BLUE_ORCHID(1, "RED_ROSE", "FLOWER_POT"),
    POTTED_BROWN_MUSHROOM(0, "FLOWER_POT"),
    POTTED_CACTUS(0, "FLOWER_POT"),
    POTTED_CORNFLOWER(0, ""),
    POTTED_DANDELION(0, "YELLOW_FLOWER", "FLOWER_POT"),
    POTTED_DARK_OAK_SAPLING(5, "SAPLING", "FLOWER_POT"),
    POTTED_DEAD_BUSH(0, "FLOWER_POT"),
    POTTED_FERN(2, "LONG_GRASS", "FLOWER_POT"),
    POTTED_JUNGLE_SAPLING(3, "SAPLING", "FLOWER_POT"),
    POTTED_LILY_OF_THE_VALLEY(0, ""),
    POTTED_OAK_SAPLING(0, "SAPLING", "FLOWER_POT"),
    POTTED_ORANGE_TULIP(5, "RED_ROSE", "FLOWER_POT"),
    POTTED_OXEYE_DAISY(8, "RED_ROSE", "FLOWER_POT"),
    POTTED_PINK_TULIP(7, "RED_ROSE", "FLOWER_POT"),
    POTTED_POPPY(0, "RED_ROSE", "FLOWER_POT"),
    POTTED_RED_MUSHROOM(0, "FLOWER_POT"),
    POTTED_RED_TULIP(4, "RED_ROSE", "FLOWER_POT"),
    POTTED_SPRUCE_SAPLING(1, "SAPLING", "FLOWER_POT"),
    POTTED_WHITE_TULIP(6, "RED_ROSE", "FLOWER_POT"),
    POTTED_WITHER_ROSE(0, ""),
    POWERED_RAIL(0, ""),
    PRISMARINE(0, ""),
    PRISMARINE_BRICKS(2, "PRISMARINE"),
    PRISMARINE_BRICK_SLAB(4, "STEP"),
    PRISMARINE_BRICK_STAIRS(0, "1.13"),
    PRISMARINE_CRYSTALS(0, ""),
    PRISMARINE_SHARD(0, ""),
    PRISMARINE_SLAB(0, "1.13"),
    PRISMARINE_STAIRS(0, "1.13"),
    PRISMARINE_WALL(0, ""),
    PUFFERFISH(3, "RAW_FISH"),
    PUFFERFISH_BUCKET(0, "1.13", "BUCKET", "WATER_BUCKET"),
    PUFFERFISH_SPAWN_EGG(0, "1.13", "MONSTER_EGG"),
    PUMPKIN(0, ""),
    PUMPKIN_PIE(0, ""),
    PUMPKIN_SEEDS(0, ""),
    PUMPKIN_STEM(0, ""),
    PURPLE_BANNER(5, "BANNER", "STANDING_BANNER"),
    PURPLE_BED(10, "BED", "BED_BLOCK"),
    PURPLE_CARPET(10, "CARPET"),
    PURPLE_CONCRETE(10, "CONCRETE"),
    PURPLE_CONCRETE_POWDER(10, "CONCRETE_POWDER"),
    PURPLE_DYE(5, "INK_SACK"),
    PURPLE_GLAZED_TERRACOTTA(10, "1.12", "HARD_CLAY", "STAINED_CLAY", "PURPLE_TERRACOTTA"),
    PURPLE_SHULKER_BOX(0, ""),
    PURPLE_STAINED_GLASS(10, "STAINED_GLASS"),
    PURPLE_STAINED_GLASS_PANE(10, "THIN_GLASS", "STAINED_GLASS_PANE"),
    PURPLE_TERRACOTTA(10, "HARD_CLAY", "STAINED_CLAY"),
    PURPLE_WALL_BANNER(5, "WALL_BANNER"),
    PURPLE_WOOL(10, "WOOL"),
    PURPUR_BLOCK(0, ""),
    PURPUR_PILLAR(0, ""),
    PURPUR_SLAB(0, "PURPUR_DOUBLE_SLAB"),
    PURPUR_STAIRS(0, ""),
    QUARTZ(0, ""),
    QUARTZ_BLOCK(0, ""),
    QUARTZ_PILLAR(2, "QUARTZ_BLOCK"),
    QUARTZ_SLAB(7, "STEP"),
    QUARTZ_STAIRS(0, ""),
    RABBIT(0, ""),
    RABBIT_FOOT(0, ""),
    RABBIT_HIDE(0, ""),
    RABBIT_SPAWN_EGG(101, "MONSTER_EGG"),
    RABBIT_STEW(0, ""),
    RAIL(0, "RAILS"),
    RAVAGER_SPAWN_EGG(0, "1.14"),
    REDSTONE(0, ""),
    REDSTONE_BLOCK(0, ""),
    REDSTONE_LAMP(0, "REDSTONE_LAMP_OFF", "REDSTONE_LAMP_ON"),
    REDSTONE_ORE(0, "GLOWING_REDSTONE_ORE"),
    REDSTONE_TORCH(0, "REDSTONE_TORCH_ON", "REDSTONE_TORCH_OFF"),
    REDSTONE_WALL_TORCH(1, "REDSTONE_TORCH_ON", "REDSTONE_TORCH_OFF"),
    REDSTONE_WIRE(0, ""),
    RED_BANNER(1, "BANNER", "STANDING_BANNER"),
    RED_BED(14, "BED", "BED_BLOCK"),
    RED_CARPET(14, "CARPET"),
    RED_CONCRETE(14, "CONCRETE"),
    RED_CONCRETE_POWDER(14, "CONCRETE_POWDER"),
    RED_DYE(1, "ROSE_RED"),
    RED_GLAZED_TERRACOTTA(14, "1.12", "HARD_CLAY", "STAINED_CLAY", "RED_TERRACOTTA"),
    RED_MUSHROOM(0, ""),
    RED_MUSHROOM_BLOCK(0, "RED_MUSHROOM", "HUGE_MUSHROOM_2"),
    RED_NETHER_BRICKS(0, "RED_NETHER_BRICK"),
    RED_NETHER_BRICK_SLAB(4, "STEP"),
    RED_NETHER_BRICK_STAIRS(0, ""),
    RED_NETHER_BRICK_WALL(0, ""),
    RED_SAND(1, "SAND"),
    RED_SANDSTONE(0, ""),
    RED_SANDSTONE_SLAB(0, "STONE_SLAB2", "DOUBLE_STONE_SLAB2"),
    RED_SANDSTONE_STAIRS(0, ""),
    RED_SANDSTONE_WALL(0, ""),
    RED_SHULKER_BOX(0, ""),
    RED_STAINED_GLASS(14, "STAINED_GLASS"),
    RED_STAINED_GLASS_PANE(14, "THIN_GLASS", "STAINED_GLASS_PANE"),
    RED_TERRACOTTA(14, "HARD_CLAY", "STAINED_CLAY"),
    RED_TULIP(4, "RED_ROSE"),
    RED_WALL_BANNER(1, "WALL_BANNER"),
    RED_WOOL(14, "WOOL"),
    REPEATER(0, "DIODE", "DIODE_BLOCK_ON", "DIODE_BLOCK_OFF"),
    REPEATING_COMMAND_BLOCK(0, "COMMAND", "COMMAND_REPEATING"),
    ROSE_BUSH(4, "DOUBLE_PLANT"),
    ROTTEN_FLESH(0, ""),
    SADDLE(0, ""),
    SALMON(1, "RAW_FISH"),
    SALMON_BUCKET(0, "1.13", "BUCKET", "WATER_BUCKET"),
    SALMON_SPAWN_EGG(0, "1.13", "MONSTER_EGG"),
    SAND(0, ""),
    SANDSTONE(0, ""),
    SANDSTONE_SLAB(1, "STEP", "STONE_SLAB", "DOUBLE_STEP"),
    SANDSTONE_STAIRS(0, ""),
    SANDSTONE_WALL(0, ""),
    SCAFFOLDING(0, "1.14", "SLIME_BLOCK"),
    SCUTE(0, "1.13"),
    SEAGRASS(0, "1.13"),
    SEA_LANTERN(0, ""),
    SEA_PICKLE(0, "1.13"),
    SHEARS(0, ""),
    SHEEP_SPAWN_EGG(91, "MONSTER_EGG"),
    SHIELD(0, ""),
    SHULKER_BOX(0, "PURPLE_SHULKER_BOX"),
    SHULKER_SHELL(0, ""),
    SHULKER_SPAWN_EGG(69, "MONSTER_EGG"),
    SILVERFISH_SPAWN_EGG(60, "MONSTER_EGG"),
    SKELETON_HORSE_SPAWN_EGG(28, "MONSTER_EGG"),
    SKELETON_SKULL(0, "SKULL", "SKULL_ITEM"),
    SKELETON_SPAWN_EGG(51, "MONSTER_EGG"),
    SKELETON_WALL_SKULL(0, "SKULL", "SKULL_ITEM"),
    SKULL_BANNER_PATTERN(0, ""),
    SLIME_BALL(0, ""),
    SLIME_BLOCK(0, ""),
    SLIME_SPAWN_EGG(55, "MONSTER_EGG"),
    SMITHING_TABLE(0, ""),
    SMOKER(0, "1.14", "FURNACE"),
    SMOOTH_QUARTZ(0, "1.13"),
    SMOOTH_QUARTZ_SLAB(7, "STEP"),
    SMOOTH_QUARTZ_STAIRS(0, ""),
    SMOOTH_RED_SANDSTONE(2, "RED_SANDSTONE"),
    SMOOTH_RED_SANDSTONE_SLAB(0, "STONE_SLAB2"),
    SMOOTH_RED_SANDSTONE_STAIRS(0, ""),
    SMOOTH_SANDSTONE(2, "SANDSTONE"),
    SMOOTH_SANDSTONE_SLAB(0, "STEP"),
    SMOOTH_SANDSTONE_STAIRS(0, ""),
    SMOOTH_STONE(0, "STEP"),
    SMOOTH_STONE_SLAB(0, "STEP"),
    SNOW(0, ""),
    SNOWBALL(0, "SNOW_BALL"),
    SNOW_BLOCK(0, ""),
    SOUL_SAND(0, ""),
    SPAWNER(0, "MOB_SPAWNER"),
    SPECTRAL_ARROW(0, ""),
    SPIDER_EYE(0, ""),
    SPIDER_SPAWN_EGG(52, "MONSTER_EGG"),
    SPLASH_POTION(0, ""),
    SPONGE(0, ""),
    SPRUCE_BOAT(0, "BOAT_SPRUCE"),
    SPRUCE_BUTTON(0, "WOOD_BUTTON"),
    SPRUCE_DOOR(0, "SPRUCE_DOOR_ITEM"),
    SPRUCE_FENCE(0, ""),
    SPRUCE_FENCE_GATE(0, ""),
    SPRUCE_LEAVES(1, "LEAVES"),
    SPRUCE_LOG(1, "LOG"),
    SPRUCE_PLANKS(1, "WOOD"),
    SPRUCE_PRESSURE_PLATE(0, "WOOD_PLATE"),
    SPRUCE_SAPLING(1, "SAPLING"),
    SPRUCE_SIGN(0, "SIGN"),
    SPRUCE_SLAB(1, "WOOD_STEP", "WOODEN_SLAB", "WOOD_DOUBLE_STEP"),
    SPRUCE_STAIRS(0, "SPRUCE_WOOD_STAIRS"),
    SPRUCE_TRAPDOOR(0, "TRAP_DOOR"),
    SPRUCE_WALL_SIGN(0, "SIGN_POST", "WALL_SIGN"),
    SPRUCE_WOOD(1, "LOG"),
    SQUID_SPAWN_EGG(94, "MONSTER_EGG"),
    STICK(0, ""),
    STICKY_PISTON(0, "PISTON_BASE", "PISTON_STICKY_BASE"),
    STONE(0, ""),
    STONECUTTER(0, "1.14"),
    STONE_AXE(0, ""),
    STONE_BRICKS(0, "SMOOTH_BRICK"),
    STONE_BRICK_SLAB(4, "STEP", "STONE_SLAB", "DOUBLE_STEP"),
    STONE_BRICK_STAIRS(0, "SMOOTH_STAIRS"),
    STONE_BRICK_WALL(0, ""),
    STONE_BUTTON(0, ""),
    STONE_HOE(0, ""),
    STONE_PICKAXE(0, ""),
    STONE_PRESSURE_PLATE(0, "STONE_PLATE"),
    STONE_SHOVEL(0, "STONE_SPADE"),
    STONE_SLAB(0, "STEP", "DOUBLE_STEP"),
    STONE_STAIRS(0, ""),
    STONE_SWORD(0, ""),
    STRAY_SPAWN_EGG(6, "MONSTER_EGG"),
    STRING(0, ""),
    STRIPPED_ACACIA_LOG(0, "LOG_2"),
    STRIPPED_ACACIA_WOOD(0, "LOG_2"),
    STRIPPED_BIRCH_LOG(2, "LOG"),
    STRIPPED_BIRCH_WOOD(2, "LOG"),
    STRIPPED_DARK_OAK_LOG(0, "LOG"),
    STRIPPED_DARK_OAK_WOOD(0, "LOG"),
    STRIPPED_JUNGLE_LOG(3, "LOG"),
    STRIPPED_JUNGLE_WOOD(3, "LOG"),
    STRIPPED_OAK_LOG(0, "LOG"),
    STRIPPED_OAK_WOOD(0, "LOG"),
    STRIPPED_SPRUCE_LOG(1, "LOG"),
    STRIPPED_SPRUCE_WOOD(1, "LOG"),
    STRUCTURE_BLOCK(0, ""),
    STRUCTURE_VOID(0, "1.10", "BARRIER/1.9"), // Originally developers used barrier blocks for its purpose.
    SUGAR(0, ""),
    SUGAR_CANE(0, "SUGAR_CANE_BLOCK"),
    SUNFLOWER(0, "DOUBLE_PLANT"),
    SUSPICIOUS_STEW(0, "1.14", "MUSHROOM_STEW"),
    SWEET_BERRIES(0, "1.14"),
    SWEET_BERRY_BUSH(0, "1.14", "GRASS"),
    TALL_GRASS(2, "DOUBLE_PLANT"),
    TALL_SEAGRASS(0, "1.13"),
    TERRACOTTA(0, "HARD_CLAY"),
    TIPPED_ARROW(0, ""),
    TNT(0, ""),
    TNT_MINECART(0, "EXPLOSIVE_MINECART"),
    TORCH(0, ""),
    TOTEM_OF_UNDYING(0, "TOTEM"),
    TRADER_LLAMA_SPAWN_EGG(103, "1.14", "MONSTER_EGG"),
    TRAPPED_CHEST(0, ""),
    TRIDENT(0, "1.13"),
    TRIPWIRE(0, ""),
    TRIPWIRE_HOOK(0, ""),
    TROPICAL_FISH(2, "RAW_FISH"),
    TROPICAL_FISH_BUCKET(0, "1.13", "BUCKET", "WATER_BUCKET"),
    TROPICAL_FISH_SPAWN_EGG(0, "1.13", "MONSTER_EGG"),
    TUBE_CORAL(0, "1.13"),
    TUBE_CORAL_BLOCK(0, "1.13"),
    TUBE_CORAL_FAN(0, "1.13"),
    TUBE_CORAL_WALL_FAN(0, ""),
    TURTLE_EGG(0, "1.13", "EGG"),
    TURTLE_HELMET(0, "1.13"),
    TURTLE_SPAWN_EGG(0, "1.13", "MONSTER_EGG"),
    VEX_SPAWN_EGG(35, "MONSTER_EGG"),
    VILLAGER_SPAWN_EGG(120, "MONSTER_EGG"),
    VINDICATOR_SPAWN_EGG(36, "MONSTER_EGG"),
    VINE(0, ""),
    VOID_AIR(0, "AIR"),
    WALL_TORCH(0, "TORCH"),
    WANDERING_TRADER_SPAWN_EGG(0, "1.14", "VILLAGER_SPAWN_EGG"),
    WATER(0, "STATIONARY_WATER"),
    WATER_BUCKET(0, ""),
    WET_SPONGE(1, "SPONGE"),
    WHEAT(0, "CROPS"),
    WHEAT_SEEDS(0, "SEEDS"),
    WHITE_BANNER(15, "BANNER", "STANDING_BANNER"),
    WHITE_BED(0, "BED", "BED_BLOCK"),
    WHITE_CARPET(0, "CARPET"),
    WHITE_CONCRETE(0, "CONCRETE"),
    WHITE_CONCRETE_POWDER(0, "CONCRETE_POWDER"),
    WHITE_DYE(15, "1.14", "INK_SACK", "BONE_MEAL"),
    WHITE_GLAZED_TERRACOTTA(0, "1.12", "HARD_CLAY", "STAINED_CLAY", "WHITE_TERRACOTTA"),
    WHITE_SHULKER_BOX(0, ""),
    WHITE_STAINED_GLASS(0, "STAINED_GLASS"),
    WHITE_STAINED_GLASS_PANE(0, "THIN_GLASS", "STAINED_GLASS_PANE"),
    WHITE_TERRACOTTA(0, "HARD_CLAY", "TERRACOTTA"),
    WHITE_TULIP(6, "RED_ROSE"),
    WHITE_WALL_BANNER(15, "WALL_BANNER"),
    WHITE_WOOL(0, "WOOL"),
    WITCH_SPAWN_EGG(66, "MONSTER_EGG"),
    WITHER_ROSE(0, "1.14", "BLACK_DYE"),
    WITHER_SKELETON_SKULL(1, "SKULL", "SKULL_ITEM"),
    WITHER_SKELETON_SPAWN_EGG(5, "MONSTER_EGG"),
    WITHER_SKELETON_WALL_SKULL(1, "SKULL", "SKULL_ITEM"),
    WOLF_SPAWN_EGG(95, "MONSTER_EGG"),
    WOODEN_AXE(0, "WOOD_AXE"),
    WOODEN_HOE(0, "WOOD_HOE"),
    WOODEN_PICKAXE(0, "WOOD_PICKAXE"),
    WOODEN_SHOVEL(0, "WOOD_SPADE"),
    WOODEN_SWORD(0, "WOOD_SWORD"),
    WRITABLE_BOOK(0, "BOOK_AND_QUILL"),
    WRITTEN_BOOK(0, ""),
    YELLOW_BANNER(11, "BANNER", "STANDING_BANNER"),
    YELLOW_BED(4, "BED", "BED_BLOCK"),
    YELLOW_CARPET(4, "CARPET"),
    YELLOW_CONCRETE(4, "CONCRETE"),
    YELLOW_CONCRETE_POWDER(4, "CONCRETE_POWDER"),
    YELLOW_DYE(11, "INK_SACK", "DANDELION_YELLOW"),
    YELLOW_GLAZED_TERRACOTTA(4, "1.12", "HARD_CLAY", "STAINED_CLAY", "YELLOW_TERRACOTTA"),
    YELLOW_SHULKER_BOX(0, ""),
    YELLOW_STAINED_GLASS(4, "STAINED_GLASS"),
    YELLOW_STAINED_GLASS_PANE(4, "THIN_GLASS", "STAINED_GLASS_PANE"),
    YELLOW_TERRACOTTA(4, "HARD_CLAY", "STAINED_CLAY"),
    YELLOW_WALL_BANNER(11, "WALL_BANNER"),
    YELLOW_WOOL(4, "WOOL"),
    ZOMBIE_HEAD(2, "SKULL", "SKULL_ITEM"),
    ZOMBIE_HORSE_SPAWN_EGG(29, "MONSTER_EGG"),
    ZOMBIE_PIGMAN_SPAWN_EGG(57, "MONSTER_EGG"),
    ZOMBIE_SPAWN_EGG(54, "MONSTER_EGG"),
    ZOMBIE_VILLAGER_SPAWN_EGG(27, "MONSTER_EGG"),
    ZOMBIE_WALL_HEAD(2, "SKULL", "SKULL_ITEM");


    /**
     * A list of material names that can be damaged.
     * Some names are not complete as this list needs to be
     * checked with {@link String#contains}.
     */
    public static final String[] DAMAGEABLE = {
            "HELMET", "CHESTPLATE", "LEGGINGS", "BOOTS",
            "SWORD", "AXE", "PICKAXE", "SHOVEL", "HOE",
            "ELYTRA", "TRIDENT", "HORSE_ARMOR", "BARDING",
            "SHEARS", "FLINT_AND_STEEL", "BOW", "FISHING_ROD",
            "CARROT_ON_A_STICK", "CARROT_STICK"
    };
    /**
     * A list of duplicated items in 1.13 and 1.12 with different purpose.
     * Values are the new material names.
     * Duplicates are only checked by keys not values.
     * Checked with {@link String#equals}
     */
    public static final HashMap<MaterialControl, MaterialControl> DUPLICATED = new HashMap<MaterialControl, MaterialControl>() {{
        put(MaterialControl.MELON, MaterialControl.MELON_SLICE);
        put(MaterialControl.CARROT, MaterialControl.CARROTS);
        put(MaterialControl.POTATO, MaterialControl.POTATOES);
        put(MaterialControl.BEETROOT, MaterialControl.BEETROOTS);
        put(MaterialControl.BROWN_MUSHROOM, MaterialControl.BROWN_MUSHROOM_BLOCK);
        put(MaterialControl.BRICK, MaterialControl.BRICKS);
        put(MaterialControl.RED_MUSHROOM, MaterialControl.RED_MUSHROOM_BLOCK);
        put(MaterialControl.MAP, MaterialControl.FILLED_MAP);
        put(MaterialControl.NETHER_BRICK, MaterialControl.NETHER_BRICKS);
    }};
    public static final MaterialControl[] VALUES = MaterialControl.values();
    private static final HashMap<String, MaterialControl> CACHED_SEARCH = new HashMap<>();
    private static MinecraftVersion version;
    private static Boolean isNewVersion;
    private final byte data;
    private final String[] legacy;

    MaterialControl(int data, String... legacy) {
        this.data = (byte) data;
        this.legacy = legacy;
    }

    /**
     * Checks if the version is 1.13 (Aquatic Update) or higher.
     *
     * @return true if 1.13 or higher.
     */
    public static boolean isNewVersion() {
        if (isNewVersion != null) return isNewVersion;
        return isNewVersion = isVersionOrHigher(MinecraftVersion.VERSION_1_13);
    }

    public static boolean isOneEight() {
        return getVersion() == MinecraftVersion.VERSION_1_8;
    }

    /**
     * Uses newly added materials to minecraft to detect the server version.
     *
     * @return the current server version.
     */
    public static MinecraftVersion getVersion() {
        if (version != null) return version;
        return version = valueOfVersion(Bukkit.getVersion());
    }

    /**
     * When using newer versions of Minecraft {@link #isNewVersion()} this helps
     * to find the old material name with its data using a cached search for optimization.
     *
     * @see #matchXMaterial(String, byte)
     */
    private static MaterialControl requestOldXMaterial(String name, byte data) {
        MaterialControl cached = CACHED_SEARCH.get(name + "," + data);

        if (cached != null) return cached;
        Optional<MaterialControl> search = data == -1 ? Arrays.stream(MaterialControl.VALUES).filter(mat -> mat.matchAnyLegacy(name)).findFirst()
                : Arrays.stream(MaterialControl.VALUES).filter(mat -> mat.matchAnyLegacy(name) && mat.data == data).findFirst();

        if (search.isPresent()) {
            MaterialControl found = search.get();
            CACHED_SEARCH.put(found.legacy[0] + "," + found.getData(), found);
            return found;
        }
        return null;
    }

    /**
     * Checks if MaterialControl enum contains a material with this name.
     *
     * @param name name of the material
     * @return true if MaterialControl enum has this material.
     */
    public static boolean contains(String name) {
        String formatted = format(name);
        return Arrays.stream(MaterialControl.VALUES).anyMatch(mat -> mat.name().equals(formatted));
    }

    /**
     * Checks if the given material matches any of the legacy names.
     *
     * @param name the material name.
     * @return true if it's a legacy name.
     */
    public static boolean containsLegacy(String name) {
        String formatted = format(name);
        return Arrays.stream(Arrays.stream(MaterialControl.VALUES).map(m -> m.legacy).toArray(String[]::new)).anyMatch(mat
                -> parseLegacyVersionMaterialName(mat).equals(formatted));
    }

    /**
     * @see #matchXMaterial(String, byte)
     */
    public static MaterialControl matchXMaterial(Material material) {
        return matchXMaterial(material.name());
    }

    /**
     * @see #matchXMaterial(String, byte)
     */
    public static MaterialControl matchXMaterial(String name) {
        // -1 Determines whether the item's data is unknown and only the name is given.
        // Checking if the item is damageable won't do anything as the data is not going to be checked in requestOldMaterial anyway.
        return matchXMaterial(name, (byte) -1);
    }

    /**
     * Parses the material name and data argument as a {@link Material}.
     *
     * @param name name of the material
     * @param data data of the material
     */
    public static Material parseMaterial(String name, byte data) {
        return matchXMaterial(name, data).parseMaterial();
    }

    /**
     * @param item the ItemStack to match its material and data.
     * @see #matchXMaterial(String, byte)
     */
    @SuppressWarnings("deprecation")
    public static MaterialControl matchXMaterial(ItemStack item) {
        return isDamageable(item.getType().name()) ? matchXMaterial(item.getType().name(), (byte) 0) :
                matchXMaterial(item.getType().name(), (byte) item.getDurability());
    }

    /**
     * Matches the argument string and its data with a MaterialControl.
     *
     * @param name the name of the material
     * @param data the data byte of the material
     * @return a MaterialControl from the enum (with the same legacy name and data if in older versions.)
     */
    public static MaterialControl matchXMaterial(String name, byte data) {
        Validate.notEmpty(name, "Material name cannot be null or empty");
        name = format(name);

        if ((contains(name) && data <= 0) && (isNewVersion() || !isDuplicated(name)))
            return valueOf(name);

        // TODO Temporary but works - Please find a more reasonable fix for duplicated materials.
        if (isDuplicated(name) && !isNewVersion())
            return requestDuplicatedXMaterial(name, data);

        return requestOldXMaterial(name, data);
    }

    /**
     * Gets the MaterialControl based on the Material's ID and data.
     * You should avoid using this for performance reasons.
     *
     * @param id   the ID (Magic value) of the material.
     * @param data the data of the material.
     * @return some MaterialControl, or null.
     */
    public static MaterialControl matchXMaterial(int id, byte data) {
        return Arrays.stream(MaterialControl.VALUES).filter(mat -> mat.getId() == id && mat.data == data).findFirst().orElse(null);
    }

    /**
     * This method is temporary. Do not use this.
     * Manually parses the duplicated materials to find the exact material based on the server version.
     *
     * @param name the name of the material.
     * @return the duplicated MaterialControl based on the version.
     */
    private static MaterialControl requestDuplicatedXMaterial(String name, byte data) {
        MaterialControl mat = requestOldXMaterial(name, data);
        return mat == null ? null : mat.name().endsWith("S") ? valueOf(name) : mat;
    }

    /**
     * Always returns the value.
     *
     * @param name the name of the material.
     * @return the new MaterialControl of this duplicated material.
     * @see #getXMaterialIfDuplicated(String)
     */
    public static MaterialControl getNewXMaterialIfDuplicated(String name) {
        return DUPLICATED.entrySet().stream()
                .filter(m -> m.getKey().name().equals(format(name)))
                .findFirst()
                .map(Map.Entry::getValue)
                .orElse(null);
    }

    /**
     * Checks if the item is duplicated for a different purpose in new versions from {@link #DUPLICATED}.
     *
     * @param name the name of the material.
     * @return the other MaterialControl (key or value) of the MaterialControl (key or value) which the name was equals to.
     * @see #matchXMaterial(String, byte)
     */
    public static MaterialControl getXMaterialIfDuplicated(String name) {
        String formatted = format(name);
        Optional<Map.Entry<MaterialControl, MaterialControl>> mat = DUPLICATED.entrySet().stream().filter(m
                -> m.getKey().name().equals(formatted) || m.getValue().name().equals(formatted)).findFirst();

        if (mat.isPresent()) {
            Map.Entry<MaterialControl, MaterialControl> found = mat.get();
            return formatted.equals(found.getKey().name()) ? found.getValue() : found.getKey();
        }
        return null;
    }

    /**
     * Attempts to build the string like an enum name.
     *
     * @param name the material name to modify.
     * @return a Material enum name.
     */
    private static String format(String name) {
        return name.toUpperCase().replace("MINECRAFT:", "").replace('-', '_').replaceAll("\\s+", "_").replaceAll("\\W", "");
    }

    /**
     * Parses the material name if the legacy name has a version attached to it.
     *
     * @param name the material name to parse.
     * @return the material name with the version removed.
     */
    private static String parseLegacyVersionMaterialName(String name) {
        if (!name.contains("/")) return name;
        return name.substring(0, name.indexOf('/'));
    }

    /**
     * Checks if the version argument is the same or higher than the current server version.
     *
     * @param version the version to be checked.
     * @return true of the version is equal or higher than the current version.
     */
    public static boolean isVersionOrHigher(MinecraftVersion version) {
        MinecraftVersion current = getVersion();

        if (version == current) return true;
        if (version == MinecraftVersion.UNKNOWN) return false;
        if (current == MinecraftVersion.UNKNOWN) return true;

        int ver = Integer.parseInt(version.name().replace("VERSION_", "").replace("_", ""));
        int currentVer = Integer.parseInt(current.name().replace("VERSION_", "").replace("_", ""));

        return currentVer >= ver;
    }

    /**
     * Converts the material's name to a string with the first letter uppercase.
     *
     * @return a converted string.
     */
    public static String toWord(Material material) {
        return material.name().charAt(0) + material.name().substring(1).toLowerCase();
    }

    /**
     * Compares two major versions. The current server version and the given version.
     *
     * @param version the version to check.
     * @return true if is the same as the current version or higher.
     */
    public static boolean isVersionOrHigher(String version) {
        int currentVer = Integer.parseInt(getExactMajorVersion(Bukkit.getVersion()).replace(".", ""));
        int versionNumber = Integer.parseInt(version.replace(".", ""));

        return currentVer >= versionNumber;
    }

    /**
     * Gets the exact major version (..., 1.9, 1.10, ..., 1.14)
     *
     * @param version Supports {@link Bukkit#getVersion()}, {@link Bukkit#getBukkitVersion()} and normal formats such as "1.14"
     * @return the exact major version.
     */
    public static String getExactMajorVersion(String version) {
        // getBukkitVersion()
        if (version.contains("SNAPSHOT") || version.contains("-R"))
            version = version.substring(0, version.indexOf("-"));
        // getVersion()
        if (version.contains("git")) version = version.substring(version.indexOf("MC:") + 4).replace(")", "");
        if (version.split(Pattern.quote(".")).length > 2) version = version.substring(0, version.lastIndexOf("."));
        return version;
    }

    /**
     * Parses the string arugment to a version.
     * Supports {@link Bukkit#getVersion()}, {@link Bukkit#getBukkitVersion()} and normal formats such as "1.14"
     *
     * @param version the server version.
     * @return the Minecraft version represented by the string.
     */
    private static MinecraftVersion valueOfVersion(String version) {
        version = getExactMajorVersion(version);
        if ("1.10".equals(version) || "1.11".equals(version) || "1.12".equals(version))
            return MinecraftVersion.VERSION_1_9;
        version = version.replace(".", "_");
        if (!version.startsWith("VERSION_")) version = "VERSION_" + version;
        String check = version;
        return Arrays.stream(MinecraftVersion.VALUES).anyMatch(v -> v.name().equals(check)) ? MinecraftVersion.valueOf(version) : MinecraftVersion.UNKNOWN;
    }

    /**
     * Checks if the material can be damaged from {@link #DAMAGEABLE}.
     *
     * @param name the name of the material.
     * @return true of the material can be damaged.
     */
    public static boolean isDamageable(String name) {
        return Arrays.stream(DAMAGEABLE).anyMatch(name::contains);
    }

    public static boolean isDuplicated(String name) {
        String formatted = format(name);
        return DUPLICATED.entrySet().stream().anyMatch(x -> x.getKey().name().equals(formatted));
    }

    /**
     * Gets the ID (Magic value) of the material.
     * If an {@link IllegalArgumentException} was thrown from this method,
     * you should definitely report it.
     *
     * @return the ID of the material. -1 if it's a new block.
     */
    @SuppressWarnings("deprecation")
    public int getId() {
        return isNew() ? -1 : parseMaterial() != null ? parseMaterial().getId() : -1;
    }

    public boolean isDuplicated() {
        return DUPLICATED.containsKey(this);
    }

    /**
     * Checks if the given string matches any of this material's legacy material names.
     *
     * @param name the name to check
     * @return true if it's one of the legacy names.
     */
    public boolean matchAnyLegacy(String name) {
        String formatted = format(name);
        return Arrays.asList(this.legacy).contains(formatted);
    }

    /**
     * Converts the material's name to a string with the first letter uppercase.
     *
     * @return a converted string.
     */
    public String toWord() {
        return this.name().charAt(0) + this.name().substring(1).toLowerCase();
    }

    /**
     * Checks if the item is duplicated for a different purpose in new versions from {@link #DUPLICATED}.
     *
     * @return true if the item's name is duplicated.
     * @see #matchXMaterial(String, byte)
     */
    public MaterialControl getXMaterialIfDuplicated() {
        Optional<Map.Entry<MaterialControl, MaterialControl>> mat = DUPLICATED.entrySet().stream().filter(m -> m.getKey() == this).findFirst();
        return mat.map(Map.Entry::getValue).orElse(null);
    }

    /**
     * @return true if the item can be damaged.
     * @see #isDamageable(String)
     */
    public boolean isDamageable() {
        return isDamageable(this.name());
    }

    /**
     * Get the {@link ItemStack} data of this material in older versions.
     * Which can be accessed with {@link ItemStack#getData()} then MaterialData#getData()
     * or {@link ItemStack#getDurability()} if not damageable.
     *
     * @return data of this material.
     */
    public int getData() {
        return this.data;
    }

    /**
     * Get a list of materials names that was previously used by older versions.
     *
     * @return a list of string of legacy material names.
     */
    public String[] getLegacy() {
        return this.legacy;
    }

    /**
     * Parses the MaterialControl as an {@link ItemStack}.
     *
     * @return an ItemStack with the same material (and data if in older versions.)
     */
    public ItemStack parseItem() {
        return parseItem(false);
    }

    /**
     * Parses the MaterialControl as an {@link ItemStack}.
     *
     * @param suggest if true {@link #parseMaterial(boolean)}
     * @return an ItemStack with the same material (and data if in older versions.)
     */
    @SuppressWarnings("deprecation")
    public ItemStack parseItem(boolean suggest) {
        Material material = this.parseMaterial(suggest);
        return isNewVersion() ? new ItemStack(material) : new ItemStack(material, 1, this.data);
    }

    /**
     * Parses the MaterialControl as a {@link Material}.
     *
     * @return the Material related to this MaterialControl based on the server version.
     */
    public Material parseMaterial() {
        return parseMaterial(false);
    }

    /**
     * Parses the MaterialControl as a {@link Material}.
     *
     * @param suggest Use a suggested material if the material is added in the new version.
     * @return the Material related to this MaterialControl based on the server version.
     * @see #matchXMaterial(String, byte)
     */
    public Material parseMaterial(boolean suggest) {
        Material newMat = Material.getMaterial(this.name());

        // If the name is not null it's probably the new version.
        // So you can still use this name even if it's a duplicated name.
        // Since duplicated names only apply to older versions.
        if (newMat != null && (isNewVersion() || !this.isDuplicated())) return newMat;
        return requestOldMaterial(suggest);
    }

    /**
     * Parses from old material names and can accept suggestions.
     *
     * @param suggest Accept suggestions for newly added blocks
     * @return A parsed Material suitable for this minecraft version.
     */
    private Material requestOldMaterial(boolean suggest) {
        Material oldMat;
        boolean isNew = getVersionIfNew() != MinecraftVersion.UNKNOWN;
        for (int i = this.legacy.length - 1; i >= 0; i--) {
            String legacyName = this.legacy[i];
            // Slash means it's just another name for the material in another version.
            if (legacyName.contains("/")) {
                oldMat = Material.getMaterial(parseLegacyVersionMaterialName(legacyName));

                if (oldMat != null) return oldMat;
                else continue;
            }
            if (isNew) {
                if (suggest) {
                    oldMat = Material.getMaterial(legacyName);
                    if (oldMat != null) return oldMat;
                } else return null;
                // According to the suggestion format list, all the other names continuing
                // from here are considered as a "suggestion" if there's no slash anymore.
            }
            oldMat = Material.getMaterial(legacyName);
            if (oldMat != null) return oldMat;
        }
        return null;
    }

    /**
     * Checks if an item is similar to the material and its data (if in older versions.)
     *
     * @param item item to check.
     * @return true if the material is the same as the item's material (and data if in older versions.)
     */
    @SuppressWarnings("deprecation")
    public boolean isSimilar(ItemStack item) {
        Objects.requireNonNull(item, "ItemStack cannot be null");
        Objects.requireNonNull(item.getType(), "ItemStack's material cannot be null");
        return (isNewVersion() || this.isDamageable()) ? item.getType() == this.parseMaterial() : item.getType() == this.parseMaterial() && item.getDurability() == this.data;
    }

    /**
     * Get the suggested material names that can be used instead of this material.
     *
     * @return a list of suggested material names.
     */
    public String[] getSuggestions() {
        if (!this.legacy[0].contains(".")) return new String[0];
        return Arrays.stream(this.legacy).filter(mat -> !mat.contains(".")).toArray(String[]::new);
    }

    /**
     * Checks if this material is supported in the current version.
     * It'll check both the newest matetrial name and for legacy names.
     *
     * @return true if the material exists in {@link Material} list.
     */
    public boolean isSupported() {
        return Arrays.stream(Material.values()).anyMatch(mat -> mat.name().equals(this.name()) || this.matchAnyLegacy(mat.name()));
    }

    /**
     * Gets the added version if the material is newly added after the 1.13 Aquatic Update and higher.
     *
     * @return the version which the material was added in. {@link MinecraftVersion#UNKNOWN} if not new.
     * @see #isNew()
     */
    public MinecraftVersion getVersionIfNew() {
        return this.isNew() ? valueOfVersion(this.legacy[0]) : MinecraftVersion.UNKNOWN;
    }

    /**
     * Checks if the material is newly added after the 1.13 Aquatic Update.
     *
     * @return true if it was newly added.
     */
    public boolean isNew() {
        return this.legacy[0].contains(".");
    }

    /**
     * Gets the suggested material instead of returning null for unsupported versions.
     * This is somehow similar to what ProtcolSupport and ViaVersion are doing to new materials.
     * Don't use this if you want to parse to a {@link Material}
     *
     * @return The suggested material that is similar.
     * @see #parseMaterial()
     */
    public MaterialControl suggestOldMaterialIfNew() {
        if (getVersionIfNew() == MinecraftVersion.UNKNOWN || this.legacy.length == 1) return null;

        // We need a loop because: Newest -> Oldest
        for (int i = this.legacy.length - 1; i >= 0; i--) {
            String legacyName = this.legacy[i];

            if (legacyName.contains("/")) continue;
            MaterialControl mat = matchXMaterial(parseLegacyVersionMaterialName(legacyName), this.data);
            if (mat != null && this != mat) return mat;
        }
        return null;
    }

    /**
     * Only major versions related to material changes.
     */
    public enum MinecraftVersion {
        /**
         * Bountiful Update
         */
        VERSION_1_8,
        /**
         * Combat Update (Pitiful Update?)
         */
        VERSION_1_9,
        /**
         * Aquatic Update
         */
        VERSION_1_13,
        /**
         * Village Pillage Update
         */
        VERSION_1_14,
        /**
         * 1.7 or below.
         * Using {@link #getVersionIfNew()} it means 1.12 or below.
         */
        UNKNOWN;

        public static final MinecraftVersion[] VALUES = MinecraftVersion.values();
    }

}